

#include "DBManager/Repository/HDF5/Input/Table/TABRND1Repository.h"

#include "DBManager/Repository/HDF5/Base/HDF5RepositoryMacro.h"

HDF5_REG_REPOSITORY(TABRND1Repository)

using namespace SG::DBManager::HDF5;
using namespace SG::DataStructure;
using namespace SG::DataStructure::FEM;
using namespace SG::DataStructure::Common;

// 构造函数实现
TABRND1Repository::TABRND1Repository(HDF5Database& database)
    : SG::DBManager::HDF5::MainlyRepositoryBase<MainStruct>(database) {}

void TABRND1Repository::InitialDatasetInfo() {
  RegisterTableInfo<SG::DataStructure::Common::Id>(
      "/OWN/INDEX/INPUT/TABLE/TABRND1", IndexDataset);
  RegisterTableInfo<NasMainStruct>("/SG/INPUT/TABLE/TABRND1/IDENTITY",
                                   MainDataset);
  RegisterTableInfo<SubStruct>("/SG/INPUT/TABLE/TABRND1/F", SubDataset);
}

void TABRND1Repository::DumpWriteCahce() {
  auto& writeStorage = this->GetMainCache().m_writeStorage;

  // 1. flag设置为无顺序
  GetMainDatasetInfo().SetIsSequential(false);

  // 主表数据
  std::vector<NasMainStruct> IDENTITYData{};
  // 附表数据
  std::vector<SubStruct> subData;

  // 2. 转换为nastran格式数据
  OwnToNastran(writeStorage, IDENTITYData, subData);

  // 3. 写出数据至文件
  WriteData(MainDataset, IDENTITYData);
  WriteData(SubDataset, subData);

  // 4. 更新Index表
  this->WriteIndexData(this->GetIndexDatasetInfo(), writeStorage);

  // 5. 清空缓存
  writeStorage.clear();
}

std::vector<TABRND1Repository::DataType>* TABRND1Repository::LoadReadCache(
    std::size_t loadIndex) {
  // 1. 读取范围内主表数据
  std::vector<NasMainStruct> IDENTITYData;
  LoadMainMetadata(loadIndex, IDENTITYData);

  if (IDENTITYData.empty()) {
    return nullptr;
  }

  // 2. 读取范围内附表数据
  std::vector<SubStruct> subData;

  LoadSecondaryMetadata(IDENTITYData, POS, LEN, SubDataset, subData);

  // 3. 将数据转换为自己的格式放入缓存
  auto* cacheVector = m_cacheHelper.LookupOrCreateVector<DataType>(
      GetMainCache().m_readCacheKey, IDENTITYData.size());
  NastranToOwn(IDENTITYData, subData, *cacheVector);
  return cacheVector;
}

void TABRND1Repository::SortData() {
  // 1. 读取主表数据
  std::vector<NasMainStruct> IDENTITYData;
  GetDataset(MainDataset).read(IDENTITYData);

  if (IDENTITYData.empty()) {
    GetMainDatasetInfo().SetIsSequential(true);
    return;
  }

  // 2. 读取附表数据
  std::vector<SubStruct> subData;

  GetDataset(SubDataset).read(subData);

  // 3. 将所有数据转换
  std::vector<MainStruct> AllData{};
  NastranToOwn(IDENTITYData, subData, AllData);

  // 4. 排序
  std::sort(AllData.begin(), AllData.end());

  // 5. 转换回nastran格式
  OwnToNastran(AllData, IDENTITYData, subData, true);

  // 6. 写出主表数据至文件
  GetDataset(MainDataset).write(IDENTITYData);
  // 7. 写出附表数据至文件
  GetDataset(SubDataset).write(subData);

  // 8. 重写索引
  RewriteIndexData(AllData);

  // 9. 设置为已顺序
  GetMainDatasetInfo().SetIsSequential(true);
}

std::vector<TABRND1Repository::MainStruct> TABRND1Repository::GetAllData() {
  Sort();

  std::vector<MainStruct> result;

  std::vector<NasMainStruct> IDENTITYData;
  GetDataset(MainDataset).read(IDENTITYData);

  if (IDENTITYData.empty()) {
    return result;
  }

  std::vector<SubStruct> subData;

  GetDataset(SubDataset).read(subData);

  // 将所有数据转换
  NastranToOwn(IDENTITYData, subData, result);

  return result;
}

void TABRND1Repository::OwnToNastran(
    std::vector<MainStruct>& own, std::vector<NasMainStruct>& _OUT IDENTITYData,
    std::vector<SubStruct>& _OUT subData,

    bool isSort) {
  subData.clear();

  IDENTITYData.clear();
  IDENTITYData.reserve(own.size());

  // 获取已有数据条数，主要是放在主表的POS字段
  // 如果是重新排序的时候，Pos都是从0 开始的
  size_t count = isSort ? 0 : this->GetDatasetInfo(SubDataset).GetRowCount();

  // OwnIdent 代表咱们自己的数据结构
  // NasIdent 代表nastran的数据结构
  for (auto& OwnIdent : own) {
    // 写入附表
    subData.insert(subData.end(), OwnIdent.m_XYList.begin(),
                   OwnIdent.m_XYList.end());

    const size_t len = OwnIdent.m_XYList.size();

    // 写入IDENTITY
    NasMainStruct NasIdent{};

    NasIdent.ID = OwnIdent.m_id;
    NasIdent.CODEX = OwnIdent.m_CODEX;
    NasIdent.CODEY = OwnIdent.m_CODEY;
    NasIdent.DOMAIN_ID = OwnIdent.m_domainId;

    NasIdent.POS = static_cast<I64>(count);

    NasIdent.LEN = static_cast<I64>(len);

    IDENTITYData.emplace_back(NasIdent);

    count += len;
  }
}

void TABRND1Repository::NastranToOwn(std::vector<NasMainStruct>& IDENTITYData,
                                     std::vector<SubStruct>& subData,

                                     std::vector<MainStruct>& _OUT own) {
  own.clear();
  own.reserve(IDENTITYData.size());

  // 代表初始的Index 位置,
  // 因为数据有可能是截取了附表的一部分，所有主表中根据POS找的时候需要对应一下，
  // 比如第一个主表数据中POS字段为10000， 附表的vector的数据
  // 就是从附表中的第10000个开始对应的 也就是Index==0的
  // const I64 index = IDENTITYData[0].POS;

  MainStruct const tempown;
  own.resize(IDENTITYData.size(), tempown);

  for (size_t i = 0; i < IDENTITYData.size(); i++) {
    auto& OwnIdent = own[i];
    auto& NasIdent = IDENTITYData[i];

    OwnIdent.m_id = NasIdent.ID;
    OwnIdent.m_CODEX = NasIdent.CODEX;
    OwnIdent.m_CODEY = NasIdent.CODEY;
    OwnIdent.m_domainId = NasIdent.DOMAIN_ID;

    if (NasIdent.LEN != 0) {
      OwnIdent.m_XYList.assign(
          subData.begin() + NasIdent.POS - IDENTITYData[0].POS,
          subData.begin() + NasIdent.POS + NasIdent.LEN - IDENTITYData[0].POS);
    }
  }
}
